package org.duang.server;

import java.io.IOException;
import java.net.DatagramSocket;
import java.net.ServerSocket;

import org.duang.kit.PathKit;
import org.duang.kit.ToolsKit;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.webapp.WebAppContext;

public class DuangServer  implements IDuangServer {
	
	private String webAppDir;
	private int port;
	private String context;
	private boolean isRuning = false;
	private int minPort = 8760;
	private int maxPort = 8769;
	private Server server;
	private WebAppContext webApp;
	private int scanIntervalSeconds = 5;
	
	public void init(String webAppDir, int port, String context){
		if(ToolsKit.isEmpty(webAppDir)) throw new IllegalStateException("webAppDir is null");
		if(port < minPort || port > maxPort) throw new IllegalStateException("port only range is "+minPort+"~"+maxPort);
		if(ToolsKit.isEmpty(context)) throw new IllegalStateException("context is null");
		this.webAppDir = webAppDir;
		this.port = port;
		this.context = context;
	}
	
	
	public void start() {
		if(!isRuning){
			try{
				if(isUse()){
					throw new IllegalStateException("port: " + port + " already in use!");
				}
				server = new Server(); //创建服务容器对象
				SelectChannelConnector connector = new SelectChannelConnector();
				connector.setPort(port);
				server.addConnector(connector);
				webApp = new WebAppContext();
				webApp.setThrowUnavailableOnStartupException(true);//启动时发生异常则停止启动并退出
				webApp.setContextPath(context);
				webApp.setResourceBase(webAppDir);
				webApp.setInitParameter("org.eclipse.jetty.servlet.Default.dirAllowed", "false");
				webApp.setInitParameter("org.eclipse.jetty.servlet.Default.useFileMappedBuffer", "false");
				server.setHandler(webApp);
				if (scanIntervalSeconds > 0) {
					Scanner scanner = new Scanner(webAppDir, scanIntervalSeconds) {
						public void onChange() {
							try {
								System.err.println("\nLoading changes ......");
								webApp.stop();
								DuangClassLoader loader = new DuangClassLoader(webApp, getClassPath());
								webApp.setClassLoader(loader);
								webApp.start();
								System.err.println("Loading complete.");
							} catch (Exception e) {
								System.err.println("Error reconfiguring/restarting webapp after change in watched files");
								e.printStackTrace();
							}
						}
					};
					System.out.println("Starting scanner at interval of " + scanIntervalSeconds + " seconds.");
					scanner.start();
				}
				server.start(); // 启动服务容器
				server.join();  // 启动完成
				System.out.println("duangserver is running complete! god bless not bug...");
			} catch(Exception e){
				e.printStackTrace();
				System.exit(100);
			}
			isRuning = true;
			return;
		}
	}

	public void stop() {
		if (isRuning) {
			try {server.stop();} catch (Exception e) {e.printStackTrace();}
			isRuning = false;
		}
	}
	
	private String getClassPath() {
		return System.getProperty("java.class.path");
	}
	/**
	 * 检测本机指定端口是否可用<br/>
	 * 如果端口可用，则返回false
	 * @return
	 */
	private boolean isUse() {
		if(port < minPort || port > maxPort) throw new IllegalStateException("port only range is "+minPort+"~"+maxPort);
		 ServerSocket ss  = null;
		 DatagramSocket ds = null;
        try { 
//        	System.out.println(InetAddress.getLocalHost().getHostAddress() + "                 "+port);
            ss = new ServerSocket(port);
            ss.setReuseAddress(true);
            ds = new DatagramSocket(port);
            ds.setReuseAddress(true);
            System.out.println(ss.getInetAddress().getHostName()+":"+ ss.getLocalPort() +" is not use!");
            return false;  
        } catch (IOException e) {  
              e.printStackTrace();
        }  finally {
				try {
					if(ToolsKit.isNotEmpty(ds)) ds.close();
					if(ToolsKit.isNotEmpty(ss)) ss.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
        }
		return true;
	}
	
}
